/**
 * @file uart.c
 * @author your name (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2023-07-24
 *
 * @copyright Copyright (c) 2023
 *
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <FreeRTOS.h>
#include <queue.h>
#include <timers.h>
#include <task.h>
#include "bflb_uart.h"
#include "bflb_gpio.h"
#include "sv17f_uart.h"
#include "log.h"

/*控制指令*/
/* 播放*/
uint8_t CMD_PLAY[4] = { 0xAA, 0x02, 0x00, 0xAC };
/* 暂停*/
uint8_t CMD_PAUSE[4] = { 0xAA, 0x03, 0x00, 0xAD };
/* 停止*/
uint8_t CMD_STOP[4] = { 0xAA, 0x04, 0x00, 0xAE };
/* 上一曲*/
uint8_t CMD_SOUND_UP[4] = { 0xAA, 0x05, 0x00, 0xAF };
/* 下一曲*/
uint8_t CMD_SOUND_DOWN[4] = { 0xAA, 0x06, 0x00, 0xB0 };
/* 音量加*/
uint8_t CMD_VOL_UP[4] = { 0xAA, 0x14, 0x00, 0xBE };
/* 音量减*/
uint8_t CMD_VOL_DOWN[4] = { 0xAA, 0x15, 0x00, 0xBF };
/* 上一文件目录*/
uint8_t CMD_DIR_UP[4] = { 0xAA, 0x0E, 0x00, 0xB8 };
/* 下一文件目录*/
uint8_t CMD_DIR_DOWN[4] = { 0xAA, 0x0F, 0x00, 0xB9 };
/* 结束播放*/
uint8_t CMD_RELEASE[4] = { 0xAA, 0x10, 0x00, 0xBA };

/*查询指令*/
/*查询播放状态 返回：AA 01 01 播放状态 SM*/
uint8_t CMD_QUERY_STATUS[4] = { 0xAA, 0x01, 0x00, 0xAB };
/*查询当前在线盘符 返回：AA 09 01 盘符 SM*/
uint8_t CMD_QUERY_PAN[4] = { 0xAA, 0x09, 0x00, 0xB3 };
/*查询当前播放盘符 返回：AA 0A 01 盘符 SM*/
uint8_t CMD_QUERY_PLAY_PAN[4] = { 0xAA, 0x0A, 0x00, 0xB4 };
/*查询总曲目 返回：AA 0C 02 总曲目高 总曲目低 SM*/
uint8_t CMD_QUERY_SUM_SOUND[4] = { 0xAA, 0x0C, 0x00, 0xB6 };
/*查询当前曲目 返回：AA 0D 02 曲目高 曲目低 SM*/
uint8_t CMD_QUERY_CUR_SOUND[4] = { 0xAA, 0x0D, 0x00, 0xB7 };
/*查询文件夹目录曲目 返回：AA 11 02 曲目高 曲目低 SM*/
uint8_t CMD_QUERY_DIR_SOUND[4] = { 0xAA, 0x11, 0x00, 0xBB };
/*查询文件夹目录总曲目 返回：AA 12 02 曲目高 曲目低 SM*/
uint8_t CMD_QUERY_SUM_DIR_SOUND[4] = { 0xAA, 0x12, 0x00, 0xBC };

/*设置指令 */
/*音量设置 0xAA, 0x13, 0x01, 音量, SM*/
uint8_t VOL_SET[5] = { 0xAA, 0x13, 0x01, 0x00, 0x00 };
/*设置循环模式 0xAA, 0x18, 0x01, 循环模式, SM*/
uint8_t LOOP_SET[5] = { 0xAA, 0x18, 0x01, 0x00, 0x00 };
/*设置循环次数 0xAA, 0x19, 0x02, 次数高, 次数低, SM*/
uint8_t LOOP_COUNT_SET[6] = { 0xAA, 0x19, 0x02, 0x00, 0x00, 0x00 };
/*EQ设置 0xAA, 0x1A, 0x01, EQ, SM*/
uint8_t EQ_SET[5] = { 0xAA, 0x1A, 0x01, 0x00, 0x00 };
/*指定曲目 0xAA, 0x07, 0x02, 曲目高, 曲目低, SM*/
uint8_t SEL_SOUND_SET[6] = { 0xAA, 0x07, 0x02, 0x00, 0x00, 0x00 };
/*指定盘符指定路径 0xAA, 0x08, 长度, 盘符, 路径, SM*/
uint8_t PAN_SET[6] = { 0xAA, 0x08, 0x00, 0x00, 0x00, 0x00 };
/*切换到指定盘符径 0xAA, 0x0B, 0x01, 盘符, SM*/
uint8_t SEL_PAN_SET[5] = { 0xAA, 0x0B, 0x01, 0x00, 0x00 };
/*指定曲目播放 0xAA, 0x16, 0x03, 盘符, 曲目高, 曲目低, SM*/
uint8_t SEL_PAN_SOUND_SET[7] = { 0xAA, 0x16, 0x03, 0x00, 0x00, 0x00, 0x00 };
/*指定路径播放 0xAA, 0x17, 长度, 盘符, 路径, SM*/
uint8_t SEL_DIR_SOUND_SET[6] = { 0xAA, 0x17, 0x00, 0x00, 0x00, 0x00 };
/*选曲不播放 0xAA, 0x1F, 0x02, 曲目高, 曲目低, SM*/
uint8_t CHECK_SOUND_SET[6] = { 0xAA, 0x1F, 0x02, 0x00, 0x00, 0x00 };

static void sv17f_uart_init(void);
static struct bflb_device_s *sound_uart;
static char uart_buff[8] = { 0 };
xQueueHandle sound_queue;
extern xQueueHandle rf_queue;

void sv17f_CMD_LOG(uint8_t *cmd_buf, uint8_t size)
{
    printf("sv17f_CMD_LOG: ");
    for (int i = 0; i < size; i++) {
        printf("0x%02X ", cmd_buf[i]);
    }
    printf("\r\n");
}

/*计算校验码*/
uint8_t check_sum(uint8_t *ck_buf, uint8_t size)
{
    uint8_t checkSum = 0x00;
    for (int i = 0; i < size; i++) {
        checkSum += ck_buf[i];
    }
    return checkSum;
}

/*音量设置 0xAA, 0x13, 0x01, 音量, SM*/
int sv17f_set_vol(uint8_t vol)
{
    if (vol > 0x30) {
        vol = 0x30;
    } else if (vol < 0x00) {
        vol = 0x00;
    }
    VOL_SET[3] = vol;
    VOL_SET[4] = check_sum(VOL_SET, 4);
    sv17f_CMD_LOG(VOL_SET, 5);
    int ret;
    ret = bflb_uart_put(sound_uart, VOL_SET, sizeof(VOL_SET));

    return ret;
}
/*设置循环模式 0xAA, 0x18, 0x01, 循环模式, SM*/
int sv17f_set_loop(uint8_t loop)
{
    LOOP_SET[3] = loop;
    LOOP_SET[4] = check_sum(LOOP_SET, 4);
    int ret;
    sv17f_CMD_LOG(LOOP_SET, 5);
    ret = bflb_uart_put(sound_uart, LOOP_SET, sizeof(LOOP_SET));
    return ret;
}
/*设置循环次数 0xAA, 0x19, 0x02, 次数高, 次数低, SM*/
int sv17f_set_count(uint8_t count)
{
    LOOP_COUNT_SET[3] = (count >> 8) & 0xFF;
    LOOP_COUNT_SET[4] = count & 0xFF;
    LOOP_COUNT_SET[5] = check_sum(LOOP_COUNT_SET, 5);
    int ret;
    ret = bflb_uart_put(sound_uart, LOOP_COUNT_SET, sizeof(LOOP_COUNT_SET));
    return ret;
}
/*EQ设置 0xAA, 0x1A, 0x01, EQ, SM*/
int sv17f_set_eq(uint8_t eq)
{
    int ret;
    EQ_SET[3] = eq;
    EQ_SET[4] = check_sum(EQ_SET, 4);
    sv17f_CMD_LOG(EQ_SET, 5);
    ret = bflb_uart_put(sound_uart, EQ_SET, sizeof(EQ_SET));
    return ret;
}
/*指定曲目（会播放）*/
int sv17f_set_sound(uint16_t sound)
{
    int ret;
    SEL_SOUND_SET[3] = sound >> 8 & 0xFF;
    SEL_SOUND_SET[4] = sound & 0xFF;
    SEL_SOUND_SET[5] = check_sum(SEL_SOUND_SET, 5);
    ret = bflb_uart_put(sound_uart, SEL_SOUND_SET, sizeof(SEL_SOUND_SET));
    return ret;
}
/*指定盘符指定路径 0xAA, 0x08, 长度, 盘符, 路径, SM*/
int sv17f_set_pan(uint8_t pan)
{
    int ret;
    PAN_SET[3] = (pan >> 8) & 0xFF;
    PAN_SET[4] = pan & 0xFF;
    PAN_SET[5] = check_sum(PAN_SET, 5);
    sv17f_CMD_LOG(PAN_SET, 6);
    ret = bflb_uart_put(sound_uart, PAN_SET, sizeof(PAN_SET));
    return ret;
}
/*切换到指定盘符径 0xAA, 0x0B, 0x01, 盘符, SM*/
int sv17f_set_sel_pan(uint8_t pan)
{
    int ret;
    SEL_PAN_SET[3] = pan;
    SEL_PAN_SET[4] = check_sum(SEL_PAN_SET, 4);
    sv17f_CMD_LOG(SEL_PAN_SET, 5);
    ret = bflb_uart_put(sound_uart, SEL_PAN_SET, sizeof(SEL_PAN_SET));
    return ret;
}
/*指定曲目播放 0xAA, 0x16, 0x03, 盘符, 曲目高, 曲目低, SM*/
int sv17f_set_sel_sound_paly(uint8_t pan, uint16_t sound)
{
    int ret;
    SEL_PAN_SOUND_SET[3] = pan;
    SEL_PAN_SOUND_SET[4] = sound >> 8 & 0xFF;
    SEL_PAN_SOUND_SET[5] = sound & 0xFF;
    SEL_PAN_SOUND_SET[6] = check_sum(SEL_PAN_SOUND_SET, 6);
    sv17f_CMD_LOG(SEL_PAN_SOUND_SET, 7);
    ret = bflb_uart_put(sound_uart, SEL_PAN_SOUND_SET, sizeof(SEL_PAN_SOUND_SET));
    return ret;
}
/*指定路径播放 0xAA, 0x17, 长度, 盘符, 路径, SM*/
int sv17f_set_sel_dir_paly(uint8_t pan, uint8_t dir)
{
    int ret;
    // SEL_DIR_SOUND_SET[2] = 盘符长度+路径长度=1+路径长度;
    SEL_DIR_SOUND_SET[3] = pan;
    SEL_DIR_SOUND_SET[4] = dir;
    SEL_DIR_SOUND_SET[5] = check_sum(SEL_DIR_SOUND_SET, 5);
    ret = bflb_uart_put(sound_uart, SEL_DIR_SOUND_SET, sizeof(SEL_DIR_SOUND_SET));
    return ret;
}

/*选曲不播放 1-65535*/
int sv17f_check_sel_sound(uint16_t sound)
{
    int ret;
    CHECK_SOUND_SET[3] = sound >> 8 & 0xFF;
    CHECK_SOUND_SET[4] = sound & 0xFF;
    CHECK_SOUND_SET[5] = check_sum(CHECK_SOUND_SET, 5);
    ret = bflb_uart_put(sound_uart, CHECK_SOUND_SET, sizeof(CHECK_SOUND_SET));
    return ret;
}

/* 查询播放状态*/
uint8_t sv17f_play_status(uint16_t timeout)
{
    int ret = bflb_uart_put(sound_uart, CMD_QUERY_STATUS, 4);
    while (!bflb_uart_rxavailable(sound_uart) && (--timeout)) {
        bflb_mtimer_delay_ms(1);
    }
    int i;
    uint8_t rx_buf[5] = { 0 };
    printf("sv17f_play_status: ");
    while (bflb_uart_rxavailable(sound_uart)) {
        uint8_t tmp = bflb_uart_getchar(sound_uart);
        printf("0x%02x ", tmp);
        if (tmp == 0xAA) {
            rx_buf[0] = tmp;
            for (i = 1; i < 5; i++) {
                rx_buf[i] = bflb_uart_getchar(sound_uart);
            }
        } else {
            printf("0x%02x ", tmp);
            memset(rx_buf, 0, 5);
        }
    }
    printf("\r\n ");
    sv17f_CMD_LOG(rx_buf, 5);
    return rx_buf[3];
}

/* 查询当前在线盘符*/
uint8_t sv17f_online_pan(uint16_t timeout)
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_QUERY_PAN, sizeof(CMD_QUERY_PAN));
    while (!bflb_uart_rxavailable(sound_uart) && (--timeout)) {
        bflb_mtimer_delay_ms(1);
    }
    int i;
    uint8_t rx_buf[5] = { 0 };
    while (bflb_uart_rxavailable(sound_uart)) {
        uint8_t tmp = bflb_uart_getchar(sound_uart);
        if (tmp == 0xAA) {
            rx_buf[0] = tmp;
            for (i = 1; i < 5; i++) {
                rx_buf[i] = bflb_uart_getchar(sound_uart);
            }
        } else {
            memset(rx_buf, 0, 5);
        }
    }
    sv17f_CMD_LOG(rx_buf, 5);
    return rx_buf[3];
}

/* 查询当前播放盘符*/
uint8_t sv17f_use_pan(uint16_t timeout)
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_QUERY_PLAY_PAN, sizeof(CMD_QUERY_PLAY_PAN));
    while (!bflb_uart_rxavailable(sound_uart) && (--timeout)) {
        bflb_mtimer_delay_ms(1);
    };
    int i;
    uint8_t rx_buf[5] = { 0 };
    while (bflb_uart_rxavailable(sound_uart)) {
        uint8_t tmp = bflb_uart_getchar(sound_uart);
        if (tmp == 0xAA) {
            rx_buf[0] = tmp;
            for (i = 1; i < 5; i++) {
                rx_buf[i] = bflb_uart_getchar(sound_uart);
            }
        } else {
            memset(rx_buf, 0, 5);
        }
    }
    sv17f_CMD_LOG(rx_buf, 5);
    return rx_buf[3];
}

/* 查询总曲目*/
uint8_t sv17f_sum_sound(uint16_t timeout)
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_QUERY_SUM_SOUND, sizeof(CMD_QUERY_SUM_SOUND));
    while (!bflb_uart_rxavailable(sound_uart) && (--timeout)) {
        bflb_mtimer_delay_ms(1);
    }
    int i;
    uint8_t rx_buf[6] = { 0 };
    while (bflb_uart_rxavailable(sound_uart)) {
        uint8_t tmp = bflb_uart_getchar(sound_uart);
        if (tmp == 0xAA) {
            rx_buf[0] = tmp;
            for (i = 1; i < 6; i++) {
                rx_buf[i] = bflb_uart_getchar(sound_uart);
            }
        } else {
            memset(rx_buf, 0, 6);
        }
    }
    sv17f_CMD_LOG(rx_buf, 6);
    return rx_buf[3] << 8 + rx_buf[4];
}
/* 查询当前曲目*/
uint8_t sv17f_cur_sound(uint16_t timeout)
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_QUERY_CUR_SOUND, sizeof(CMD_QUERY_CUR_SOUND));
    while (!bflb_uart_rxavailable(sound_uart) && (--timeout)) {
        bflb_mtimer_delay_ms(1);
    }
    int i;
    uint8_t rx_buf[6] = { 0 };
    while (bflb_uart_rxavailable(sound_uart)) {
        uint8_t tmp = bflb_uart_getchar(sound_uart);
        if (tmp == 0xAA) {
            rx_buf[0] = tmp;
            for (i = 1; i < 6; i++) {
                rx_buf[i] = bflb_uart_getchar(sound_uart);
            }
        } else {
            memset(rx_buf, 0, 6);
        }
    }
    sv17f_CMD_LOG(rx_buf, 6);
    return rx_buf[3] << 8 + rx_buf[4];
}

/* 查询文件夹目录曲目*/
uint16_t sv17f_dir_sound(uint16_t timeout)
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_QUERY_DIR_SOUND, sizeof(CMD_QUERY_DIR_SOUND));
    while (!bflb_uart_rxavailable(sound_uart) && (--timeout)) {
        bflb_mtimer_delay_ms(1);
    }
    int i;
    uint8_t rx_buf[6] = { 0 };
    while (bflb_uart_rxavailable(sound_uart)) {
        uint8_t tmp = bflb_uart_getchar(sound_uart);
        if (tmp == 0xAA) {
            rx_buf[0] = tmp;
            for (i = 1; i < 6; i++) {
                rx_buf[i] = bflb_uart_getchar(sound_uart);
            }
        } else {
            memset(rx_buf, 0, 6);
        }
    }
    sv17f_CMD_LOG(rx_buf, 6);
    uint16_t result = rx_buf[3] << 8;
    return result + rx_buf[4];
}
/* 查询文件夹目录总曲目*/
uint16_t sv17f_sum_dir_sound(uint16_t timeout)
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_QUERY_SUM_DIR_SOUND, sizeof(CMD_QUERY_SUM_DIR_SOUND));
    while (!bflb_uart_rxavailable(sound_uart) && (--timeout)) {
        bflb_mtimer_delay_ms(1);
    }
    int i;
    uint8_t rx_buf[6] = { 0 };
    while (bflb_uart_rxavailable(sound_uart)) {
        uint8_t tmp = bflb_uart_getchar(sound_uart);
        if (tmp == 0xAA) {
            rx_buf[0] = tmp;
            for (i = 1; i < 6; i++) {
                rx_buf[i] = bflb_uart_getchar(sound_uart);
            }
        } else {
            memset(rx_buf, 0, 6);
        }
    }
    sv17f_CMD_LOG(rx_buf, 6);
    uint16_t result = rx_buf[3] << 8;
    return result + rx_buf[4];
}

/* 播放*/
int sv17f_play()
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_PLAY, sizeof(CMD_PLAY));
    return ret;
}
/* 暂停*/
int sv17f_pasue()
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_PAUSE, sizeof(CMD_PAUSE));
    return ret;
}
/* 停止*/
int sv17f_stop()
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_STOP, sizeof(CMD_STOP));
    return ret;
}
/* 上一曲*/
int sv17f_sound_up()
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_SOUND_UP, sizeof(CMD_SOUND_UP));
    return ret;
}
/* 下一曲*/
int sv17f_sound_down()
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_SOUND_DOWN, sizeof(CMD_SOUND_DOWN));
    return ret;
}
/* 音量加*/
int sv17f_vol_up()
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_VOL_UP, sizeof(CMD_VOL_UP));
    return ret;
}
/* 音量减*/
int sv17f_vol_down()
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_VOL_DOWN, sizeof(CMD_VOL_DOWN));
    return ret;
}
/* 上一文件目录*/
int sv17f_dir_up()
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_DIR_UP, sizeof(CMD_DIR_UP));
    return ret;
}
/* 下一文件目录*/
int sv17f_dir_down()
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_DIR_DOWN, sizeof(CMD_DIR_DOWN));
    return ret;
}
/* 结束播放*/
int sv17f_release()
{
    int ret;
    ret = bflb_uart_put(sound_uart, CMD_RELEASE, sizeof(CMD_RELEASE));
    return ret;
}

void sv17f_init(const struct sv17f_config_s *config)
{
    sv17f_set_vol(config->volume);
    sv17f_set_loop(config->loop_mode);
    sv17f_set_eq(config->eq);
    sv17f_check_sel_sound(1);
}

void sv17f_uart_task(void *arg)
{
    char *buf = NULL;
    sound_queue = xQueueCreate(1, 8);
    struct sv17f_config_s sv17f_cfg = {
        .volume = VOLUME_LEVEL_30,
        .loop_mode = LOOP_MODE_SINGLE_STOP,
        .eq = EQ_NOMARL,
        .pan = PAN_SD
    };

    sv17f_uart_init();
    sv17f_init(&sv17f_cfg);

    // LOG_E("播放状态： 0x%02x \r\n", sv17f_play_status(2000));
    while (1) {
        buf = pvPortMalloc(8);
        memset(buf, 0, 8);
        xQueueReceive(sound_queue, buf, portMAX_DELAY);
        uint16_t sound;
        if (buf[4] == 0xFF && buf[5] == 0x00) {
            sound = (0x00 << 8) | buf[3];
        } else {
            sound = (buf[3] << 8) | buf[4];
        }
        LOG_E("sound： 0x%04x \r\n", sound);
        sv17f_set_sound(sound);
        // sv17f_play();
        // sv17f_set_pan(config->pan);
        LOG_E("播放状态： 0x%02x \r\n", sv17f_play_status(2000));
        vTaskDelay(10 / portTICK_PERIOD_MS);
    }
}

/**
 * @brief
 *
*/
static void sv17f_uart_init()
{
    struct bflb_device_s *gpio;
    struct bflb_uart_config_s sound_cfg = {
        .baudrate = 9600,
        .data_bits = UART_DATA_BITS_8,
        .stop_bits = UART_STOP_BITS_1,
        .parity = UART_PARITY_NONE,
        .flow_ctrl = 0,
        .tx_fifo_threshold = 4,
        .rx_fifo_threshold = 4,
    };

    gpio = bflb_device_get_by_name("gpio");

    sound_uart = bflb_device_get_by_name("uart1");

    bflb_gpio_uart_init(gpio, GPIO_PIN_25, GPIO_UART_FUNC_UART1_TX);
    bflb_gpio_uart_init(gpio, GPIO_PIN_26, GPIO_UART_FUNC_UART1_RX);

    bflb_uart_init(sound_uart, &sound_cfg);
}